meta:
  id: ref-block
  title: ref-block
  file-extension: ref
  ks-version: 0.9
  endian: be
  bit-endian: be
  ks-opaque-types: true
  imports:
    - varint
doc: |
  A reftable file is a portable binary file format customized for reference storage. References are sorted, enabling linear scans, binary search lookup, and range scans.
  Storage in the file is organized into variable sized blocks. Prefix compression is used within a single block to reduce disk space. Block size and alignment are tunable by the writer.
doc-ref:
  - https://git-scm.com/docs/reftable/2.45.2
  - https://about.gitlab.com/blog/2024/05/30/a-beginners-guide-to-the-git-reftable-format/
types:
  first_ref_block:
    seq:
      - id: ref_block_flag
        type: u1
        valid: 0x72
      - id: ref_block_len
        type: b24
      - id: ref_block_body
        type: ref_block_body
        size: ref_block_len - 24 - 4
  first_ref_block_body:
    seq:
      - id: records
        type: ref_records
        size: _parent.ref_block_len - 24 - 4 - 3 * restart_count - 2
      - id: restart_offset
        type: b24
        repeat: expr
        repeat-expr: restart_count
    instances:
      restart_count:
        pos: _parent.ref_block_len - 24 - 4 - 2
        type: u2
  ref_block:
    seq:
      - id: ref_block_flag
        type: u1
        valid: 0x72
      - id: ref_block_len
        type: b24
      - id: ref_block_body
        type: ref_block_body
        size: ref_block_len - 4
  ref_block_body:
    seq:
      - id: records
        type: ref_records
        size: _parent.ref_block_len - 4 - 3 * restart_count - 2
      - id: restart_offset
        type: b24
        repeat: expr
        repeat-expr: restart_count
    instances:
      restart_count:
        pos: _parent.ref_block_len - 4 - 2
        type: u2
  ref_records:
    seq:
      - id: ref_records
        type: ref_record
        repeat: eos
  ref_record:
    seq:
      - id: prefix_length
        type: varint
      - id: suffix_info
        type: varint
      - id: suffix
        type: str
        encoding: ASCII
        size: suffix_length
      - id: update_index_delta
        type: varint
      - id: value
        type: 
          switch-on: value_type
          cases:
            0: record_value_deletion
            1: record_value_one_object_name
            2: record_value_two_object_names
            3: record_value_symbolic_reference
    instances:
      suffix_length:
        value: suffix_info.value >> 3
      value_type:
        value: suffix_info.value & 0b00000111
  record_value_deletion:
    seq:
      - id: no_value
        size: 0
  record_value_one_object_name:
    seq:
      - id: oid
        size: 20
  record_value_two_object_names:
    seq:
      - id: oid
        size: 20
      - id: peeled_oid
        size: 20
  record_value_symbolic_reference:
    seq:
      - id: target_ref_len
        type: varint
      - id: target_ref
        type: str
        size: target_ref_len.value
        encoding: ASCII